﻿using Newtonsoft.Json;
using Simple.Tools;
using Simple.Tools.http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.Http
 * 接口名称 HttpHelper
 * 开发人员：ADMIN
 * 创建时间：2023/8/17 10:44:03
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.Http
{
	/// <summary>
	/// 
	/// </summary>
	public class HttpHelper: IHttpHelper
	{
		/// <summary>
		/// 
		/// </summary>
		private static Dictionary<string, HttpContextClient> clients;
		/// <summary>
		/// 
		/// </summary>
	    static HttpHelper()
		{
			clients = new Dictionary<string, HttpContextClient>();
		}
		/// <summary>
		/// 
		/// </summary>
		public HttpHelper()
		{
			this._currentKey = defaultKey;
		}

		/// <summary>
		/// 
		/// </summary>
		private static string defaultKey;

		/// <summary>
		/// 
		/// </summary>
		private  string _currentKey;
		/// <summary>
		/// 设置静态的key
		/// 每次构造初始化的时候用这个key初始化
		/// </summary>
		/// <param name="key"></param>
		public static void SetCurrentKey(string key)
		{
			if (clients.ContainsKey(key))
			{
				defaultKey = key;
			}
		}

		/// <summary>
		/// 添加客户端base url
		/// </summary>
		/// <param name="key"></param>
		/// <param name="url"></param>
		public static void AddClient(string key,string url)
		{
			if (clients.ContainsKey(key))
			{
				return;
			}
			var client=new HttpContextClient(url);
			clients.Add(key, client);
			if (SimpleCheck.IsNullOrEmpty(defaultKey))
			{
				defaultKey = key;
			}
		}

		/// <summary>
		/// 设置当前实例的Key
		/// </summary>
		public void SetKey(string key)
		{
			if (clients.ContainsKey(key))
			{
				this._currentKey = key;
			}
		}
		
		/// <summary>
		///get 请求
		/// </summary>
		/// <param name="Path"></param>
		/// <returns></returns>
		public async Task<IResponse> GetAsync(string Path)
		{
			
			var request = new HttpRequestMessage(HttpMethod.Get,Path);
			return await RequestAsync(request);
		}

		/// <summary>
		/// get 请求
		/// </summary>
		/// <param name="Path"></param>
		/// <returns></returns>
		public IResponse Get(string Path)
		{
		
			var request = new HttpRequestMessage(HttpMethod.Get, Path);
			return  Request(request);
		}
		/// <summary>
		///get 请求
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="Params"></param>
		/// <returns></returns>
		public async Task<IResponse> GetAsync(string Path,object Params)
		{
		
			return await GetAsync(StringExtension.GetParams(Path, Params));
		}
		/// <summary>
		/// get 请求
		/// </summary>
		/// <param name="Path">路径</param>
		/// <param name="Params">参数</param>
		/// <returns></returns>
		public  IResponse Get(string Path, object Params)
		{
			return  Get(StringExtension.GetParams(Path,Params));
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path">路径</param>
		/// <param name="conext">请求体</param>
		/// <param name="contextType"></param>
		/// <param name="IsFile">是否包含文件</param>
		/// <returns></returns>
		public async Task<IResponse> PostAsync(string Path,object conext,HttpContextType contextType= HttpContextType.Json,bool IsFile=false)
		{
			var request = Request(Path,conext,HttpMethod.Post,contextType,IsFile);
			return await RequestAsync(request);
		}

		/// <summary>
		/// post
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
        public async Task<IResponse> PostAsync(string Path, object conext, bool IsFile = false)
        {
			HttpContextType contextType = HttpContextType.Json;
			if (IsFile)
			{
				contextType = HttpContextType.FormData;
            }
            var request = Request(Path, conext, HttpMethod.Post, contextType, IsFile);
            return await RequestAsync(request);
        }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="contextType"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
        public  IResponse Post(string Path, object conext, HttpContextType contextType = HttpContextType.Json,bool IsFile = false)
		{
			var request = Request(Path, conext, HttpMethod.Post, contextType,IsFile);
			return  Request(request);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
        public IResponse Post(string Path, object conext,bool IsFile = false)
        {
            HttpContextType contextType= HttpContextType.Json;
            if (IsFile)
			{
				contextType = HttpContextType.FormData;
            }
            var request = Request(Path, conext, HttpMethod.Post,contextType, IsFile);
            return Request(request);
        }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="contextType"></param>
		/// <param name="IsFile">是否有文件</param>
		/// <returns></returns>
        public async Task<IResponse> PutAsync(string Path, object conext, HttpContextType contextType = HttpContextType.Json,bool IsFile=false)
		{
			var request = Request(Path,conext,HttpMethod.Put,contextType,IsFile);
			return await RequestAsync(request);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
        public async Task<IResponse> PutAsync(string Path, object conext,bool IsFile = false)
        {
			HttpContextType contextType = HttpContextType.Json;
			if (IsFile)
			{
                contextType= HttpContextType.FormData;
            }
            var request = Request(Path, conext, HttpMethod.Put, contextType, IsFile);
            return await RequestAsync(request);
        }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="contextType"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
        public IResponse Put(string Path, object conext, HttpContextType contextType = HttpContextType.Json,bool IsFile = false)
		{
			var request = Request(Path, conext, HttpMethod.Put, contextType,IsFile);
			return  Request(request);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
        public IResponse Put(string Path, object conext, bool IsFile = false)
        {
            HttpContextType contextType=HttpContextType.Json;
            if (IsFile)
			{
                contextType=HttpContextType.FormData;
            }
            var request = Request(Path, conext, HttpMethod.Put, contextType,IsFile);
            return Request(request);
        }
        /// <summary>
        /// 删除请求
        /// </summary>
        /// <param name="Path">路径</param>
        /// <returns></returns>
        public async Task<IResponse> DeleteAsync(string Path)
		{
			var request = new HttpRequestMessage(HttpMethod.Delete, Path);
			return await RequestAsync(request);
		}

		/// <summary>
		/// 删除请求
		/// </summary>
		/// <param name="Path">路径</param>
		/// <returns></returns>
		public  IResponse Delete(string Path)
		{
			var request = new HttpRequestMessage(HttpMethod.Delete, Path);
			return  Request(request);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		/// <exception cref="Exception"></exception>
		public async Task<IResponse> RequestAsync(HttpRequestMessage request)
		{
			if (request == null)
			{
				throw new Exception(nameof(request));
			}
			SetHead(request);

			if (SimpleCheck.IsNullOrEmpty(clients))
			{
				throw new Exception("请添加请求地址!");
			}
			return  await Response.Builder(clients[this._currentKey],request);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public  IResponse Request(HttpRequestMessage request)
		{
			return RequestAsync(request).Result;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		public static void AddHead(string key,object value)
		{
			clients[defaultKey].AddHead(key,value);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="key"></param>
		public static void RemoveHead(string key)
		{
			clients[defaultKey].RemoveHead(key);
		}
		/// <summary>
		/// 
		/// </summary>
		public static void ClearHead()
		{
			clients[defaultKey].ClearHead();
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="errorHandler"></param>
		public static void Error(Action<HttpResponseMessage,Exception> errorHandler)
		{
			Error(defaultKey,errorHandler);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="key"></param>
		/// <param name="errorHandler"></param>
		/// <exception cref="ArgumentNullException"></exception>
		public static void Error(string key,Action<HttpResponseMessage,Exception> errorHandler)
		{
			if (SimpleCheck.IsNull(errorHandler))
			{
				return;
			}
			if (SimpleCheck.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException(nameof(key));
			}
			clients[key].SetError(errorHandler);
		}

		/// <summary>
		/// 创建 post 和 put 对象
		/// 装配json和formdata请求数据
		/// </summary>
		/// <param name="Path"></param>
		/// <param name="conext"></param>
		/// <param name="method"></param>
		/// <param name="contextType"></param>
		/// <param name="IsFile"></param>
		/// <returns></returns>
		private HttpRequestMessage Request(string Path, object conext,HttpMethod method, HttpContextType contextType,bool IsFile)
		{
			if (SimpleCheck.IsNull(Path))
			{
				Path = string.Empty;
			}
			var request = new HttpRequestMessage(method, Path);
			string strConext = string.Empty;
			if (!SimpleCheck.IsNull(conext))
			{
				switch (contextType)
				{
					case HttpContextType.Json:
						strConext = JsonConvert.SerializeObject(conext);
						break;
					case HttpContextType.FormData:
						if (IsFile)
						{
							Type type = conext.GetType();
							MultipartFormDataContent multipartFormData = new MultipartFormDataContent();
							foreach (var item in type.GetProperties())
							{
								var val = item.GetValue(conext);

								MethodInfo m = item.PropertyType.GetMethod("OpenReadStream");

								if (SimpleCheck.IsNotNull(m))
								{
									var property = item.PropertyType.GetProperty("FileName");
									string fileName = string.Empty;
									if (SimpleCheck.IsNotNull(property))
									{
										fileName = property.GetValue(val).ToString();
									}
									Stream stream = (Stream)m.Invoke(val, null);
									multipartFormData.Add(new StreamContent(stream), item.GetColName(), fileName);
								}
								else if (val is FileStream stream)
								{
									multipartFormData.Add(new StreamContent(stream), item.GetColName(), System.IO.Path.GetFileName(stream.Name));
								}
								else
								{
									if (SimpleConstant.GetSystemType().ContainsKey(item.PropertyType.FullName))
									{
										multipartFormData.Add(new StringContent(val == null ? string.Empty : val.ToString()), item.Name);
									}
								}
							}
							request.Content = multipartFormData;

						}
						else
						{
							strConext = StringExtension.GetParams(conext);
						}
						#region 2
						//Type type = conext.GetType();
						//MultipartFormDataContent multipartFormData = new MultipartFormDataContent();
						//foreach (var item in type.GetProperties())
						//{
						//	var val = item.GetValue(conext);
						//	multipartFormData.Add(new StringContent(val==null?string.Empty:val.ToString()),item.Name);
						//}
						//try
						//{
						//	if (request.Headers.Contains("Content-Type"))
						//	{

						//	}
						//	request.Headers.Add("Content-Type", " application/x-www-form-urlencoded");
						//}
						//catch (Exception)
						//{

						//	throw;
						//}
						// multipartFormData.Headers.ContentDisposition=new ContentDispositionHeaderValue("form-data");
						//conextx.Headers.ContentDisposition= new ContentDispositionHeaderValue("form-data");
						//var data= client.PostAsync(Path, multipartFormData).Result;
						//var json=data.Content.ReadAsStringAsync().Result;
						#endregion
						break;
				}

				if (IsFile == false)
				{
					request.Content = new StringContent(strConext, Encoding.UTF8, StringExtension.HttpMediaHeader[(int)contextType]);
				}
			}
		
		
            return request;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="httpRequestMessage"></param>
		/// <exception cref="ArgumentNullException"></exception>
		private static void SetHead(HttpRequestMessage httpRequestMessage)
		{
			
            if (SimpleCheck.IsNullOrEmpty(clients[defaultKey].GetHeaders()))
            {
				return;
            }

			if (httpRequestMessage==null)
			{
				throw new ArgumentNullException(nameof(httpRequestMessage));
			}
            foreach (var header in clients[defaultKey].GetHeaders())
			{

				httpRequestMessage.Headers.Add(header.Key,header.Value.ToString());
			}
		}
	}
}
